/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002-2006
* Sleepycat Software. All rights reserved.
*
* $Id: ReadCommittedLocker.java,v 1.1 2006/05/06 08:59:10 ckaestne Exp $
*/
package com.sleepycat.je.txn;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.dbi.CursorImpl;
import com.sleepycat.je.dbi.DatabaseImpl;
import com.sleepycat.je.dbi.EnvironmentImpl;
import com.sleepycat.je.tree.BIN;
import com.sleepycat.je.tree.Key;
/**
* Extends BuddyLocker to acquire write locks using the buddy locker (the
* transaction locker). This is used for ReadCommitted (Degree 2) isolation.
*/
public class ReadCommittedLocker extends BuddyLocker {
/**
* Creates a ReadCommittedLocker.
* @param buddy is a transactional locker that will be used for acquiring
* write locks.
*/
public ReadCommittedLocker(EnvironmentImpl env, Locker buddy)
throws DatabaseException {
/*
* If the buddy param is a read-committed locker, reach in to get its
* transactional buddy locker.
*/
super(env,
(buddy instanceof ReadCommittedLocker) ?
((ReadCommittedLocker) buddy).getBuddy() : buddy);
assert getBuddy().isTransactional();
}
/**
* Creates a new instance of this txn for the same environment. No
* transactional locks are held by this object, so no locks are retained.
* newNonTxnLocker is also called for the BuddyLocker.
*/
public Locker newNonTxnLocker()
throws DatabaseException {
return new ReadCommittedLocker(envImpl, getBuddy().newNonTxnLocker());
}
/**
* Forwards write locks to the buddy locker (the transaction locker).
*
* @see Locker#lockInternal
* @Override
*/
LockResult lockInternal(long nodeId,
LockType lockType,
boolean noWait,
DatabaseImpl database)
throws DatabaseException {
if (lockType.isWriteLock()) {
return getBuddy().lockInternal(nodeId, lockType, noWait, database);
} else {
return super.lockInternal(nodeId, lockType, noWait, database);
}
}
/**
* Releases the lock from this locker, or if not owned by this locker then
* releases it from the buddy locker.
*/
public void releaseLock(long nodeId)
throws DatabaseException {
if (!lockManager.release(nodeId, this)) {
lockManager.release(nodeId, getBuddy());
}
}
/**
* Forwards this method to the transactional buddy. Since the buddy
* handles write locks, it knows whether this transaction created the node.
*/
public boolean createdNode(long nodeId)
throws DatabaseException {
return getBuddy().createdNode(nodeId);
}
/**
* Forwards this method to the transactional buddy. The buddy handles
* write locks and therefore handles abort information.
*/
public long getAbortLsn(long nodeId)
throws DatabaseException {
return getBuddy().getAbortLsn(nodeId);
}
/**
* @return the WriteLockInfo for this node.
*/
public WriteLockInfo getWriteLockInfo(long nodeId)
throws DatabaseException {
return getBuddy().getWriteLockInfo(nodeId);
}
/**
* Forwards this method to the transactional buddy. The buddy handles
* write locks and therefore handles delete information.
*/
public void addDeleteInfo(BIN bin, Key deletedKey)
throws DatabaseException {
getBuddy().addDeleteInfo(bin, deletedKey);
}
/**
* Forwards this method to the transactional buddy. The buddy Txn tracks
* cursors.
*/
public void registerCursor(CursorImpl cursor)
throws DatabaseException {
getBuddy().registerCursor(cursor);
}
/**
* Forwards this method to the transactional buddy. The buddy Txn tracks
* cursors.
*/
public void unRegisterCursor(CursorImpl cursor)
throws DatabaseException {
getBuddy().unRegisterCursor(cursor);
}
/**
* Is always transactional because the buddy locker is transactional.
*/
public boolean isTransactional() {
return true;
}
/**
* Is always read-committed isolation.
*/
public boolean isReadCommittedIsolation() {
return true;
}
}